#include "bnb_video_context.h"
#include "bnb_globals.h"
#include "logger.h"
#include <sstream>
#include <iostream>
using namespace std;

void BNBVideoContext::
initialize (int width, int height, bool fullscreen) {

  // Create the window.
  window = SDL_CreateWindow(
      BNB_WINDOW_TITLE,
      SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
      width, height,
      SDL_WINDOW_SHOWN
  );

  LOG_INFO("Window created");

  // Check for error and trigger fatal error if any.
  if (window == NULL) {
    stringstream ss;
    ss << "Unable to create a " << width << "x" << height;
    ss << " window (SDL reported : " << SDL_GetError() << ")";
    LOG_FATAL(ss);
  }

  // Initialize a renderer.
  initRenderer();

  /**
    * Attempt to go fullscreen.
    */
  if (fullscreen) {
    toggleFullscreen(true);
  }

  LOG ("Video context initialized successfully");
}

void BNBVideoContext::
initRenderer () {
  int ndrivers = SDL_GetNumVideoDrivers();
  
  // Loop to find a driver supporting hw accel.
  for (int k = 0; k < ndrivers; ++k) {
    renderer = SDL_CreateRenderer (window, k, SDL_RENDERER_ACCELERATED);
    // Found one.
    if (renderer != NULL) {
      stringstream ss;
      ss << "Renderer initialized : HW accel, driver \"";
      ss << SDL_GetVideoDriver(k) << "\"";
      LOG(ss.str());
      return;
    }
  }

  // Loop to find a driver initialized without hw accel.
  for (int k = 0; k < ndrivers; ++k) {
    renderer = SDL_CreateRenderer (window, k, SDL_RENDERER_SOFTWARE);
    // Found one.
    if (renderer != NULL) {
      stringstream ss;
      ss << "Renderer initialized : SW, driver \"";
      ss << SDL_GetVideoDriver(k) << "\"";
      LOG(ss.str());
      return;
    }
  }
}

bool BNBVideoContext::
toggleFullscreen (bool state) {
  int error_state = SDL_SetWindowFullscreen(window, state ? SDL_TRUE : SDL_FALSE);
  
  if (error_state < 0) {
    LOGN_WARNING("Unable to switch to ");
    if (state) {
      LOG_WARNING("fullscreen mode");
    }
    else {
      // This is very unlikely to happen.
      LOG_WARNING("windowed mode");
    }
  }
  else {
    stringstream ss;
    ss << "Switched to " << (state ? "fullscreen" : "windowed") << " mode.";
    LOG(ss.str());
  }
}

// TEST
#ifdef TEST_BNB_VIDEO_CONTEXT
void doQuit (int status) {
  SDL_Quit();
  if (status == EXIT_FAILURE) {
    cerr << "BnB quitted after a fatal error." << endl;
  }
  else {
    cout << "BnB quitted normally." << endl;
  }
  exit(status);
}

int main (int argc, char** argv) {

  logger_init("bnb.log", &doQuit);

  if (SDL_Init(SDL_INIT_VIDEO) < 0) {
    stringstream ss;
    ss << "Unable to initialize SDL : " << SDL_GetError();
    LOG_FATAL(ss.str());
  }
  LOG("SDL Initialized");
  
  {
    BNBVideoContext* bnbVidContext = BNBVideoContext::getInstance();

    bnbVidContext->initialize(1024, 768, false);
    SDL_Renderer* renderer = bnbVidContext->getRenderer();
    // Select the color for drawing. It is set to red here.
    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
    // Clear the entire screen to our selected color.
    SDL_RenderClear(renderer);
    // Up until now everything was drawn behind the scenes.
    // This will show the new, red contents of the window.
    SDL_RenderPresent(renderer);
    SDL_Delay(3000);

    BNBVideoContext::kill();
  }

  logger_quit();
  SDL_Quit();
  return (EXIT_SUCCESS);
}
#endif

